using UnityEngine;
using System;
using System.IO;
using System.Net.WebSockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

public class WebSocketClient : MonoBehaviour
{
    private ClientWebSocket ws;
    private string base_url = "ws://rtasr.xfyun.cn/v1/ws";
    private string end_tag = "{\"end\": true}";

    private async void Start()
    {
        string app_id = "b0dd7f0e";
        string api_key = "79c9e07f6643086f477cdf8343776cdd";
        string file_path = @"Assets/StreamingAssets/1.wav";

        string ts = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds).ToString();
        string tt = app_id + ts;
        MD5 md5 = MD5.Create();
        byte[] inputBytes = Encoding.UTF8.GetBytes(tt);
        byte[] hashBytes = md5.ComputeHash(inputBytes);
        string baseString = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();

        HMACSHA1 hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(api_key));
        byte[] signaBytes = hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(baseString));
        string signa = Convert.ToBase64String(signaBytes);

        Uri uri = new Uri($"{base_url}?appid={app_id}&ts={ts}&signa={Uri.EscapeDataString(signa)}");

        ws = new ClientWebSocket();
        await ws.ConnectAsync(uri, CancellationToken.None);

        Task tRecv = Task.Run(async () => await Receive());

        await Send(file_path);

        await Task.Delay(100); // Optional delay to ensure completion before closing
        await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed by user", CancellationToken.None);
    }

    private async Task Send(string file_path)
    {
        byte[] buffer = new byte[1280];
        using (FileStream fs = new FileStream(file_path, FileMode.Open))
        {
            int bytesRead;
            while ((bytesRead = await fs.ReadAsync(buffer, 0, buffer.Length)) > 0)
            {
                await ws.SendAsync(new ArraySegment<byte>(buffer, 0, bytesRead), WebSocketMessageType.Binary, true, CancellationToken.None);
                await Task.Delay(40); // Adjust delay if necessary
            }
        }

        await ws.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(end_tag)), WebSocketMessageType.Text, true, CancellationToken.None);
        Debug.Log("send end tag success");
    }

    private async Task Receive()
    {
        byte[] buffer = new byte[1024];
        while (ws.State == WebSocketState.Open)
        {
            WebSocketReceiveResult result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            if (result.MessageType == WebSocketMessageType.Close)
            {
                await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
            }
            else
            {
                string resultString = Encoding.UTF8.GetString(buffer, 0, result.Count);
                Debug.Log($"Received: {resultString}");

                // Handle parsing of JSON result here
                // Example:
                // var resultObj = JsonUtility.FromJson<ResultObject>(resultString);
                // Debug.Log($"Result: {resultObj.data}");
            }
        }
    }

    private async void OnDestroy()
    {
        if (ws != null && ws.State == WebSocketState.Open)
        {
            await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed by user", CancellationToken.None);
        }
    }
}
